# 1、useContext

  以前我们获取 Context 数据时,有两种方式:

类组件中
import { ThemeContext } from './context/index.js'

// 方式1
class Soners extends React.Component {
  //
  render() {
    const { theme } = this.context

    return <Button style={{ ...theme }} />
  }
}

Soners.contextType = ThemeContext
import { ThemeContext } from './context/index.js'

// 方式2✨(多用于Context嵌套中)
class Soners extends React.Component {
  //
  render() {
    return (
      <ThemeContext.Consumer>
        {(value) => {
          return <Button style={{ ...value }} />
        }}
      </ThemeContext.Consumer>
    )
  }
}

  但是依然繁琐,使用 hook 的话就变得简单的多:

import { ThemeContext } from './context/index.js'
import { useContext } from 'react'

function Soners(props) {
  const theme = useContext(ThemeContext)

  return (
    <div>
      <p style={{ color: theme.color, fontSize: theme.size }}>
        现在不是去想缺少什么的时候,该想一想凭现有的东西你能做什么。
      </p>
    </div>
  )
}

# 2、useCallback

  简单语句话:

useCallback(fn, deps) 相当于 useMemo(() => fn, deps)

  但不同的是,它是将内联回调函数及依赖项数组作为参数传入 useCallback

具体使用:useCallback (opens new window)

  其主要的应用是:

应用 1:跳过组件的重新渲染

  将函数传递给子组件时使用 useCallback,优点解析:

尽管父组件中待传普通函数状态没有发生变化,但当父组件中其他 state 发生变化时,父组件依然会重新渲染;如果子组件本身较为复杂的话,这个性能损失是非常大的。

  • 父组件
import { useCallback } from 'react'

function father(props) {
  let [msg, setMsg] = useState(0)

  let [count, setCount] = useState(1)

  let countChange = useCallback(() => {
    setCount(count + 1)
  }, [count])

  // function countChange() {
  //   setCount(count + 1)
  // }

  return (
    <div>
      <p>计数:{count}</p>
      <button onClick={countChange}>count值 +1</button>
      <Son countChange={countChange} />

      <button onClick={setMsg(Math.random())}>改变其他state状态</button>
    </div>
  )
}

// 使用 memo
export default memo(Demo)
  • 子组件
function son(props) {
  // 数组解构
  let { countChange } = props

  return (
    <div>
      <button onClick={countChange}>count值 +1</button>
    </div>
  )
}

// 使用 memo
export default memo(Demo)

# 3、useRef

useRef (opens new window)

  useRef 在 react 中,大致有两个作用:

# ① 保存数据

  此时 useRef 和 useState 类似,但也有更多不同 (opens new window)

如果你的组件需要存储一些值,但不影响渲染逻辑,请选择 useRef

  简单的说 useRef 的值变量,不会触发渲染。而 useState 的值需要使用 setXxxx(),因此会触发页面渲染

对 useCallback 案例进行优化
  • 父组件
import { useCallback } from 'react'

function father(props) {
  let [msg, setMsg] = useState(0)

  let [count, setCount] = useState(1)
  let countRef = useRef()
  countRef.current = count

  let countChange = useCallback(() => {
    setCount(countRef.current + 1)
  }, [])

  return (
    <div>
      <p>计数:{count}</p>
      <button onClick={countChange}>count值 +1</button>
      <Son countChange={countChange} />

      <button onClick={setMsg(Math.random())}>改变其他state状态</button>
    </div>
  )
}

// 使用 memo
export default memo(Demo)
import { useRef } from 'react'

export default function Counter() {
  let countRef = useRef(0)

  function handleClick() {
    // 这样并未重新渲染组件!
    countRef.current = countRef.current + 1

    // alert('You clicked ' + ref.current + ' times!');
  }

  return <button onClick={handleClick}>你点击了 {countRef.current}</button>
}

# ② 获取 DOM

  如果 useRef 作为获取 DOm 的作用的话,其使用和 在类组件中的 createRef() 类似:

类组件中
class Demo extends React.Component {
  constructor() {
    this.bookSelectRef = React.createRef()
  }

  getNativeDom() {
    console.log(this.bookSelect.current)
  }

  render() {
    return (
      <div>
        <p ref={this.bookSelectRef}>JavaScript高级程序设计</p>
        <p>你不知道的js</p>

        <button onClick={(e) => this.getNativeDom()}>获取DOM</button>
      </div>
    )
  }
}
import { useRef } from 'react'

function Demo(props) {
  const bookSelectRef = useRef(null)

  function getNativeDom() {
    console.log(bookSelectRef.current)
  }

  return (
    <div>
      <p ref={bookSelectRef}>JavaScript高级程序设计</p>
      <p>你不知道的js</p>

      <button onClick={getNativeDom}>获取DOM</button>
    </div>
  )
}

# 4、useMemo

  与 useCallback 非常相似,两者的区别如下:

// 使用useCallback
let fn = useCallback(() => {
  //
  // ……
}, [])

// 使用useMemo
let result = useMemo(() => {
  //
  return fn()
}, [])

# 5、useReducer

  useReducer 可以对一些 state 处理必须复杂的逻辑进行拆分。

useReducer (opens new window) --> 其实现的思想和 redux 极度相似

// const initialState = { count: 0 }
function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 }
    case 'decrement':
      return { count: state.count - 1 }
    default:
      throw new Error()
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, { count: 0 })
  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
      <button onClick={() => dispatch({ type: 'increment' })}>+</button>
    </>
  )
}
更新于 : 8/7/2024, 2:16:31 PM